package com.jqd.framework.core.exception;

import java.io.PrintStream;
import java.io.PrintWriter;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.jqd.framework.core.common.util.IDCreator;

public class ApplicationException extends Exception {
	
	private static final long serialVersionUID = -4340389843492219003L;
	
	protected String txnID = "";
	
	protected String message = "";
	
	protected String className = "";
	
	protected String methodName = "";
	
	protected Throwable cause = null;
	
	protected final Log log = LogFactory.getLog(this.getClass());
	
	
	public String getTxnID() {
		return this.txnID;
	}
	
	
	public ApplicationException() {
		this.txnID = IDCreator.createID();
	}
	
	
	public ApplicationException(String msg) {
		super(msg);
		this.txnID = IDCreator.createID();
		this.message = msg;
		this.logTrace();
	}
	
	
	public ApplicationException(String msg, Throwable cause) {
		super(msg, cause);
		this.cause = cause;
		this.txnID = IDCreator.createID();
		this.message = msg;
		this.logTrace();
	}
	
	
	public ApplicationException(Throwable cause) {
		super(cause);
		this.cause = cause;
	}
	
	
	/**
	 * 构造函数
	 * 
	 * 
	 * @param className
	 *            产生异常的类名
	 * 
	 * @param methodName
	 *            产生异常的方法名
	 * @param message
	 *            异常的错误信息
	 * 
	 * @param exception
	 *            所产生的异常
	 */
	public ApplicationException(String className, String methodName, String message, Throwable cause) {
		super(message, cause);
		this.className = className;
		this.methodName = methodName;
		this.message = message;
		this.cause = cause;
		this.txnID = IDCreator.createID();
		this.logTrace();
	}
	
	
	/**
	 * @param className
	 * @param methodName
	 * @param message
	 */
	public ApplicationException(String className, String methodName, String message) {
		super(message);
		this.className = className;
		this.methodName = methodName;
		this.message = message;
		this.txnID = IDCreator.createID();
		this.logTrace();
	}
	
	
	/**
	 * 构造函数
	 * 
	 * 
	 * @param txnID
	 *            产生异常的编号
	 * 
	 * @param className
	 *            产生异常的类名
	 * 
	 * @param methodName
	 *            产生异常的方法名
	 * @param message
	 *            异常的错误信息
	 * 
	 * @param exception
	 *            所产生的异常
	 */
	public ApplicationException(String txnID, String className, String methodName, String message,
			Throwable cause) {
		super(message, cause);
		this.txnID = txnID;
		this.className = className;
		this.methodName = methodName;
		this.message = message;
		this.cause = cause;
		this.logTrace();
	}
	
	
	/**
	 * @return Returns the cause.
	 */
	public Throwable getCause() {
		return (this.cause == this ? null : this.cause);
	}
	
	
	protected String getLogString() {
		StringBuffer descr = new StringBuffer();
		descr.append("error:[txnID:");
		descr.append(this.txnID + ";");
		if (this.className != null && !this.className.equals("")) {
			descr.append(this.getClass() + " in '");
			descr.append(this.className + "';");
			
		}
		if (this.methodName != null && !this.methodName.equals("")) {
			descr.append("method:");
			descr.append(this.methodName);
			descr.append(";");
		}
		descr.append("message:");
		descr.append(this.getMessage());
		descr.append("]");
		return descr.toString();
	}
	
	
	public String getErrorMessage() {
		return this.message;
	}
	
	
	public String getMessage() {
		String message = super.getMessage();
		Throwable cause = getCause();
		if (cause != null) {
			return message + "; nested exception is " + cause;
		}
		return message;
	}
	
	
	public void printStackTrace(PrintStream ps) {
		if (getCause() == null) {
			super.printStackTrace(ps);
		}
		else {
			ps.println(this);
			getCause().printStackTrace(ps);
		}
	}
	
	
	public void printStackTrace(PrintWriter pw) {
		if (getCause() == null) {
			super.printStackTrace(pw);
		}
		else {
			pw.println(this);
			getCause().printStackTrace(pw);
		}
	}
	
	
	@SuppressWarnings("rawtypes")
	public boolean contains(Class exClass) {
		if (exClass == null) {
			return false;
		}
		Throwable ex = this;
		while (ex != null) {
			if (exClass.isInstance(ex)) {
				return true;
			}
			if (ex instanceof ApplicationException) {
				
				ex = ((ApplicationException) ex).getCause();
			}
			else {
				ex = null;
			}
		}
		return false;
	}
	
	
	/**
	 * 记录异常到日志
	 */
	private void logTrace() {
		if (log.isInfoEnabled()) {
			log.info(this.getLogString());
		}
	}
	
}
